// -------------------------------------------------
// BlinKit - BlinKit Library
// -------------------------------------------------
//   File Name: chrome_client.h
// Description: ChromeClient Class
//      Author: Ziming Li
//     Created: 2021-07-14
// -------------------------------------------------
// Copyright (C) 2021 MingYang Software Technology.
// -------------------------------------------------

/*
 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple, Inc. All rights reserved.
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 * Copyright (C) 2012 Samsung Electronics. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifndef ChromeClient_h
#define ChromeClient_h

#include "blinkit/blink/public/platform/WebFocusType.h"
// BKTODO: #include "core/dom/AXObjectCache.h"
#include "blinkit/blink/renderer/core/dom/document.h"
#include "blinkit/blink/renderer/core/frame/ConsoleTypes.h"
// BKTODO: #include "core/inspector/ConsoleAPITypes.h"
#include "blinkit/blink/renderer/core/loader/frame_loader.h"
// BKTODO: #include "core/loader/NavigationPolicy.h"
#include "blinkit/blink/renderer/core/style/ComputedStyleConstants.h"
#include "blinkit/blink/renderer/platform/Cursor.h"
#include "blinkit/blink/renderer/platform/HostWindow.h"
#include "blinkit/blink/renderer/platform/popup_menu.h"
#include "blinkit/blink/renderer/platform/heap/Handle.h"
#include "blinkit/blink/renderer/platform/scroll/ScrollTypes.h"
#include "blinkit/blink/renderer/wtf/Forward.h"
#include "blinkit/blink/renderer/wtf/PassOwnPtr.h"
#include "blinkit/blink/renderer/wtf/Vector.h"

namespace blink {

class AXObject;
class ColorChooser;
class ColorChooserClient;
class DateTimeChooser;
class DateTimeChooserClient;
class Element;
class FileChooser;
class Frame;
class FloatPoint;
class GraphicsContext;
class GraphicsLayer;
class GraphicsLayerFactory;
class HitTestResult;
class HTMLFormControlElement;
class HTMLInputElement;
class HTMLSelectElement;
class IntRect;
class LocalFrame;
class Node;
class Page;
class PaintArtifact;
class PopupOpeningObserver;
class WebCompositorAnimationTimeline;
class WebFrameScheduler;

struct CompositedSelection;
struct DateTimeChooserParameters;
struct FrameLoadRequest;
struct GraphicsDeviceAdapter;
struct ViewportDescription;
struct WindowFeatures;

class ChromeClient : public HostWindow
{
public:
    virtual void chromeDestroyed(void) {}

    // The specified rectangle is adjusted for the minimum window size and the
    // screen, then setWindowRect with the adjusted rectangle is called.
    void setWindowRectWithAdjustment(const IntRect&);
    virtual IntRect windowRect() = 0;

    virtual IntRect pageRect(void);

    virtual void focus(void) {}

    virtual bool canTakeFocus(WebFocusType) { return false; }
    virtual void takeFocus(WebFocusType) {}

    virtual void focusedNodeChanged(Node*, Node*) {}

    virtual bool hadFormInteraction(void) const { return false; }

#if 0 // BKTODO:
    // The LocalFrame pointer provides the ChromeClient with context about which
    // LocalFrame wants to create the new Page. Also, the newly created window
    // should not be shown to the user until the ChromeClient of the newly
    // created Page has its show method called.
    // The FrameLoadRequest parameter is only for ChromeClient to check if the
    // request could be fulfilled. The ChromeClient should not load the request.
    virtual Page* createWindow(LocalFrame*, const FrameLoadRequest&, const WindowFeatures&, NavigationPolicy, ShouldSetOpener) = 0;
    virtual void show(NavigationPolicy = NavigationPolicyIgnore) = 0;

    void setWindowFeatures(const WindowFeatures&);
#endif

    virtual void didOverscroll(const FloatSize&, const FloatSize&, const FloatPoint&, const FloatSize&) {}

#if 0 // BKTODO:
    virtual void setToolbarsVisible(bool) = 0;
    virtual bool toolbarsVisible() = 0;

    virtual void setStatusbarVisible(bool) = 0;
    virtual bool statusbarVisible() = 0;
#endif

    virtual void setScrollbarsVisible(bool) {}
    virtual bool scrollbarsVisible() { return false; }

#if 0 // BKTODO:
    virtual void setMenubarVisible(bool) = 0;
    virtual bool menubarVisible() = 0;
#endif

    virtual void setResizable(bool) {}

#if 0 // BKTODO:
    virtual bool shouldReportDetailedMessageForSource(LocalFrame&, const String& source) = 0;
    virtual void addMessageToConsole(LocalFrame*, MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String& sourceID, const String& stackTrace) = 0;
#endif

    bool openBeforeUnloadConfirmPanel(const String& message, LocalFrame*, bool isReload);

    virtual void closeWindowSoon() = 0;

    bool openJavaScriptAlert(LocalFrame*, const String&);
    bool openJavaScriptConfirm(LocalFrame*, const String&);
    bool openJavaScriptPrompt(LocalFrame*, const String& message, const String& defaultValue, String& result);
    virtual void setStatusbarText(const String&) {}
    virtual bool tabsToLinks() { return false; }

    virtual void* webView() const = 0;

    virtual IntRect windowResizerRect(void) const;

    // Methods used by HostWindow.
    virtual WebScreenInfo screenInfo() const = 0;
    virtual void setCursor(const Cursor&, LocalFrame* localRoot) = 0;
    // End methods used by HostWindow.
    // BKTODO: virtual Cursor lastSetCursorForTesting() const = 0;

    virtual void dispatchViewportPropertiesDidChange(const ViewportDescription&) const { }

    virtual void contentsSizeChanged(LocalFrame*, const IntSize&) const {}
    virtual void pageScaleFactorChanged() const { }
    virtual float clampPageScaleFactorToLimits(float scale) const { return scale; }
    virtual void layoutUpdated(LocalFrame*) const { }

    void mouseDidMoveOverElement(const HitTestResult&);
    virtual void setToolTip(const String&, TextDirection, unsigned long cookie = 0) = 0;
    void clearToolTip();

    virtual void annotatedRegionsChanged() {}

    virtual PassOwnPtrWillBeRawPtr<ColorChooser> openColorChooser(LocalFrame*, ColorChooserClient*, const Color&) { return nullptr; }

    // This function is used for:
    //  - Mandatory date/time choosers if !ENABLE(INPUT_MULTIPLE_FIELDS_UI)
    //  - Date/time choosers for types for which LayoutTheme::supportsCalendarPicker
    //    returns true, if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
    //  - <datalist> UI for date/time input types regardless of
    //    ENABLE(INPUT_MULTIPLE_FIELDS_UI)
    virtual PassRefPtrWillBeRawPtr<DateTimeChooser> openDateTimeChooser(DateTimeChooserClient*, const DateTimeChooserParameters&) { return nullptr; }

    virtual void openTextDataListChooser(HTMLInputElement&) {}

    virtual void openFileChooser(LocalFrame*, PassRefPtr<FileChooser>);

    // Asychronous request to enumerate all files in a directory chosen by the user.
    virtual void enumerateChosenDirectory(FileChooser*) {}

    // Allows ports to customize the type of graphics layers created by this page.
    virtual GraphicsLayerFactory* graphicsLayerFactory() const { return nullptr; }

    // Pass 0 as the GraphicsLayer to detach the root layer.
    // This sets the graphics layer for the LocalFrame's WebWidget, if it has
    // one. Otherwise it sets it for the WebViewImpl.
    virtual void attachRootGraphicsLayer(GraphicsLayer*, LocalFrame* localRoot) = 0;

    // In Slimming Paint v2, called when the paint artifact is updated, to allow
    // the underlying web widget to composite it.
    virtual void didPaint(const PaintArtifact&) { }

    virtual void attachCompositorAnimationTimeline(WebCompositorAnimationTimeline*, LocalFrame* localRoot) { }
    virtual void detachCompositorAnimationTimeline(WebCompositorAnimationTimeline*, LocalFrame* localRoot) { }

    virtual void enterFullScreenForElement(Element*) { }
    virtual void exitFullScreenForElement(Element*) { }

    virtual void clearCompositedSelection() { }
    virtual void updateCompositedSelection(const CompositedSelection&) { }

    virtual void needTouchEvents(bool) = 0;

    virtual void setTouchAction(TouchAction) {}

    // Checks if there is an opened popup, called by LayoutMenuList::showPopup().
    virtual bool hasOpenedPopup() const { return false; }
    virtual GCRefPtr<PopupMenu> openPopupMenu(LocalFrame&, HTMLSelectElement&);

    // BKTODO: virtual void postAccessibilityNotification(AXObject*, AXObjectCache::AXNotification) { }
    virtual String acceptLanguages() { return String(); }

    enum DialogType {
        AlertDialog = 0,
        ConfirmDialog = 1,
        PromptDialog = 2,
        HTMLDialog = 3
    };
    virtual bool shouldOpenModalDialogDuringPageDismissal(const DialogType&, const String&, Document::PageDismissalType) const { return true; }

    virtual bool isSVGImageChromeClient() const { return false; }

    virtual bool requestPointerLock() { return false; }
    virtual void requestPointerUnlock() { }

    virtual IntSize minimumWindowSize() const { return IntSize(100, 100); }

    virtual bool isChromeClientImpl() const { return false; }

    virtual void didAssociateFormControls(const WillBeHeapVector<RefPtrWillBeMember<Element>>&, LocalFrame*) { }
    virtual void didChangeValueInTextField(HTMLFormControlElement&) { }
    virtual void didEndEditingOnTextField(HTMLInputElement&) { }
    virtual void handleKeyboardEventOnTextField(HTMLInputElement&, KeyboardEvent&) { }
    virtual void textFieldDataListChanged(HTMLInputElement&) { }
    virtual void ajaxSucceeded(LocalFrame*) { }

    // Input method editor related functions.
    virtual void didCancelCompositionOnSelectionChange() { }
    virtual void willSetInputMethodState() { }
    virtual void didUpdateTextOfFocusedElementByNonUserInput() { }
    virtual void showImeIfNeeded() { }

    virtual void registerViewportLayers() const { }

    virtual void showUnhandledTapUIIfNeeded(IntPoint, Node*, bool) { }

    virtual void onMouseDown(Node*) { }

    virtual void didUpdateTopControls() const { }

    virtual void registerPopupOpeningObserver(PopupOpeningObserver*) {}
    virtual void unregisterPopupOpeningObserver(PopupOpeningObserver*) {}

    virtual FloatSize elasticOverscroll() const { return FloatSize(); }

    // Called when observed XHR, fetch, and other fetch request with non-GET
    // method is initiated from javascript. At this time, it is not guaranteed
    // that this is comprehensive.
    virtual void didObserveNonGetFetchFromScript() const {}

    virtual PassOwnPtr<WebFrameScheduler> createFrameScheduler(void);

    float screenToViewport(float) const override;

protected:
    ChromeClient(void) = default;

    virtual void showMouseOverURL(const HitTestResult&) {}
    virtual void setWindowRect(const IntRect&) = 0;
    virtual bool openBeforeUnloadConfirmPanelDelegate(LocalFrame*, const String& message, bool isReload) { return true; }
    virtual bool openJavaScriptAlertDelegate(LocalFrame*, const String&) { return false; }
    virtual bool openJavaScriptConfirmDelegate(LocalFrame*, const String&) { return false; }
    virtual bool openJavaScriptPromptDelegate(LocalFrame*, const String& message, const String& defaultValue, String& result) { return false; }

private:
    bool canOpenModalIfDuringPageDismissal(Frame* mainFrame, DialogType, const String& message);
    void setToolTip(const HitTestResult&);

    LayoutPoint m_lastToolTipPoint;
    String m_lastToolTipText;

    FRIEND_TEST_ALL_PREFIXES(ChromeClientTest, SetToolTipFlood);
};

} // namespace blink

#endif // ChromeClient_h
